using System.Text.Json;
using WeatherSystem.API.Services;

namespace WeatherSystem.API.Services
{
    /// <summary>
    /// 天气API服务接口
    /// </summary>
    public interface IWeatherApiService
    {
        Task<WeatherApiResponse> GetCurrentWeatherAsync(decimal latitude, decimal longitude);
    }

    /// <summary>
    /// OpenWeatherMap API服务实现
    /// </summary>
    public class OpenWeatherMapService : IWeatherApiService
    {
        private readonly HttpClient _httpClient;
        private readonly IConfiguration _configuration;
        private readonly ILogger<OpenWeatherMapService> _logger;
        private readonly string _apiKey;
        private readonly string _baseUrl;

        public OpenWeatherMapService(
            HttpClient httpClient,
            IConfiguration configuration,
            ILogger<OpenWeatherMapService> logger)
        {
            _httpClient = httpClient;
            _configuration = configuration;
            _logger = logger;

            _apiKey = _configuration["OPENWEATHERMAP_API_KEY"] ??
                     throw new InvalidOperationException("OpenWeatherMap API Key not configured");
            _baseUrl = _configuration["WEATHER_API_BASE_URL"] ??
                      "https://api.openweathermap.org/data/2.5";
        }

        /// <summary>
        /// 获取当前天气数据
        /// </summary>
        public async Task<WeatherApiResponse> GetCurrentWeatherAsync(decimal latitude, decimal longitude)
        {
            try
            {
                var apiKey = _configuration["OPENWEATHERMAP_API_KEY"];
                if (string.IsNullOrEmpty(apiKey))
                {
                    _logger.LogWarning("OpenWeatherMap API密钥未配置，后台数据采集服务将不执行");

                    throw new InvalidOperationException("OpenWeatherMap API密钥未配置");
                }

                var url = $"{_baseUrl}/weather?lat={latitude}&lon={longitude}&appid={_apiKey}&units=metric";

                _logger.LogDebug("调用天气API: {Url}", url.Replace(_apiKey, "***"));

                var response = await _httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();

                var jsonContent = await response.Content.ReadAsStringAsync();
                var apiData = JsonSerializer.Deserialize<OpenWeatherMapResponse>(jsonContent, new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                });

                if (apiData == null)
                {
                    throw new InvalidOperationException("API返回数据为空");
                }

                // 转换为标准格式
                var result = new WeatherApiResponse
                {
                    Temperature = (decimal)apiData.Main.Temp,
                    Humidity = (decimal)apiData.Main.Humidity,
                    Pressure = (decimal)apiData.Main.Pressure,
                    WindSpeed = apiData.Wind?.Speed != null ? (decimal)apiData.Wind.Speed : 0,
                    WindDirection = apiData.Wind?.Deg != null ? (decimal)apiData.Wind.Deg : null,
                    Visibility = apiData.Visibility != null ? (decimal)apiData.Visibility / 1000 : null, // 转换为公里
                    UVIndex = null, // 需要额外的API调用
                    WeatherCondition = apiData.Weather?.FirstOrDefault()?.Description
                };

                _logger.LogInformation("天气数据获取成功，位置: ({Lat}, {Lon}), 温度: {Temp}°C",
                    latitude, longitude, result.Temperature);

                return result;
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "天气API请求失败，位置: ({Lat}, {Lon})", latitude, longitude);
                throw new InvalidOperationException("天气数据获取失败", ex);
            }
            catch (JsonException ex)
            {
                _logger.LogError(ex, "天气API响应解析失败，位置: ({Lat}, {Lon})", latitude, longitude);
                throw new InvalidOperationException("天气数据解析失败", ex);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取天气数据时发生未知错误，位置: ({Lat}, {Lon})", latitude, longitude);
                throw;
            }
        }
    }

    /// <summary>
    /// OpenWeatherMap API响应模型
    /// </summary>
    public class OpenWeatherMapResponse
    {
        public MainData Main { get; set; } = new();
        public WindData? Wind { get; set; }
        public int? Visibility { get; set; }
        public List<WeatherInfo>? Weather { get; set; }
        public string Name { get; set; } = string.Empty;
    }

    public class MainData
    {
        public double Temp { get; set; }
        public double Humidity { get; set; }
        public double Pressure { get; set; }
        public double Temp_Min { get; set; }
        public double Temp_Max { get; set; }
        public double? Feels_Like { get; set; }
    }

    public class WindData
    {
        public double? Speed { get; set; }
        public double? Deg { get; set; }
        public double? Gust { get; set; }
    }

    public class WeatherInfo
    {
        public int Id { get; set; }
        public string Main { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
        public string Icon { get; set; } = string.Empty;
    }

    /// <summary>
    /// 天气API服务工厂
    /// </summary>
    public static class WeatherApiServiceFactory
    {
        public static IWeatherApiService CreateService(
            string provider,
            HttpClient httpClient,
            IConfiguration configuration,
            ILogger logger)
        {
            return provider.ToLower() switch
            {
                "openweathermap" => new OpenWeatherMapService(
                    httpClient,
                    configuration,
                    (ILogger<OpenWeatherMapService>)logger),
                _ => throw new NotSupportedException($"不支持的天气API提供商: {provider}")
            };
        }
    }

    /// <summary>
    /// 天气API配置选项
    /// </summary>
    public class WeatherApiOptions
    {
        public const string SectionName = "WeatherApi";

        public string Provider { get; set; } = "openweathermap";
        public string ApiKey { get; set; } = string.Empty;
        public string BaseUrl { get; set; } = string.Empty;
        public int TimeoutSeconds { get; set; } = 30;
        public int MaxRetryAttempts { get; set; } = 3;
        public int RetryDelaySeconds { get; set; } = 5;
    }
}